package com.cjm.one.goods.apps;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cjm.one.common.config.redission.DistributedLockTemplate;
import com.cjm.one.common.exception.GlobalException;
import com.cjm.one.common.result.Result;
import com.cjm.one.common.result.ResultCodeEnum;
import com.cjm.one.common.utils.AuthCustomerContextHolder;
import com.cjm.one.goods.service.CustomerCouponService;
import com.cjm.one.model.coupon.dto.CouponConfirmDto;
import com.cjm.one.model.coupon.dto.CouponReserveDto;
import com.cjm.one.model.coupon.entity.CustomerCoupon;
import com.cjm.one.model.coupon.vo.CouponInfoVo;
import com.cjm.one.model.coupon.vo.CouponReserveVo;
import com.cjm.one.security.annotation.Within;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

@RestController
@Slf4j
@Tag(name = "4-客户领取优惠券记录", description = "客户优惠券")
@RequestMapping("/app/customer/coupon")
public class AppCustomerCouponController {
    @Resource
    private DistributedLockTemplate distributedLockTemplate;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private CustomerCouponService customerCouponService;
    @GetMapping("/list")
    @Operation(summary = "查询用户领取的优惠卷信息列表")
    public Result<Page<CouponInfoVo>> getList(@RequestParam Long current,
                                              @RequestParam Long size ,
                                              @RequestParam(name = "keyWord", required = false) String keyWord,
                                              @RequestParam(name = "rangeType", required = false) Integer rangeType) {
        log.debug("查询优惠券信息列表, 当前页码:{}, 页面大小:{}", current, size);
        Long customerId = AuthCustomerContextHolder.getAuthContextCustomer().getId();
        Page<CouponInfoVo> page = customerCouponService.getCouponInfoAppReceivedPage(current, size,keyWord, rangeType,customerId);
        return Result.ok(page);
    }

    @PostMapping("/receive")
    @Operation(summary = "领取优惠券信息")
    public Result<Boolean> save(@RequestBody CustomerCoupon customerCoupon) {
        log.debug("领取优惠券信息:{}",customerCoupon);
        LocalDateTime now = LocalDateTime.now();
        Long id = AuthCustomerContextHolder.getAuthContextCustomer().getId();
        customerCoupon.setCustomerId(id);
        customerCoupon.setReceiveTime( now);
        return Result.ok(customerCouponService.receiveCoupon(customerCoupon));
    }
    @PostMapping("/receive/auto")
    @Operation(summary = "自动领取优惠券信息")
    public Result<Boolean> autoReceive(@RequestBody @Validated CouponReserveDto couponReserveDto) {
        log.debug("领取优惠券信息:{}",couponReserveDto);

        return Result.ok(customerCouponService.autoReceiveCoupon(couponReserveDto));
    }
    /**
     * @description: 批量预占优惠券
     * @author: cjm
     * @date: 2025/3/31 15:52
     * @param: [request]
     * @return: com.cjm.one.common.result.Result<CouponReserveResponse>
     **/
    @PostMapping("/batch/reserve")
    @Operation(summary = "批量预占优惠券")
    public Result<CouponReserveVo> batchReserveCoupons(
            @RequestBody @Valid CouponReserveDto couponReserveDto) {

        // 参数校验
        if (CollectionUtils.isEmpty(couponReserveDto.getCouponIds())) {
            throw new GlobalException(ResultCodeEnum.ARGUMENT_VALID_ERROR);
        }

        // 分布式锁前缀
        String lockKey = "coupon:reserve:" + couponReserveDto.getUserId();
        return distributedLockTemplate.<CouponReserveVo>execute(
                lockKey,
                3,
                TimeUnit.SECONDS,
                () -> Result.ok(customerCouponService.processReserve(couponReserveDto))
        );
    }
    /**
     * @description: 批量确认使用优惠券
     * @author: cjm
     * @date: 2025/3/31 15:55
     * @param: [request]
     * @return: com.cjm.one.common.result.Result<java.lang.Boolean>
     **/
    @Transactional
    @PostMapping("/batch/confirm")
    @Operation(summary = "批量确认使用")
    @Within
    public Result<Boolean> batchConfirmUse(
            @RequestBody @Valid CouponConfirmDto couponConfirmDto) {

        // 幂等性校验
        String idempotentKey = "coupon:confirm:" + couponConfirmDto.getOrderId();
        if (!redisTemplate.opsForValue().setIfAbsent(idempotentKey, "1", 5, TimeUnit.MINUTES)) {
            throw new GlobalException(ResultCodeEnum.REPEAT_SUBMIT);
        }

        try {
            return customerCouponService.confirmUsage(couponConfirmDto);
        } finally {

        }
    }


}
